use crate::error::AppError;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, MySqlPool};

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, FromRow)]
pub struct Message {
    pub id: i32,
    pub user_id: i32,
    pub chat_id: i32,
    pub content: String,
    pub files: String,
    pub create_at: chrono::DateTime<chrono::Local>,
    pub update_at: chrono::DateTime<chrono::Local>,
}

impl Message {
    pub async fn create(&self, pool: &MySqlPool) -> Result<u64, AppError> {
        //verify content - not empty
        if self.content.is_empty() {
            return Err(AppError::CreateMessageError("content is empty".to_string()));
        }
        //verify files exists
        if self.files.is_empty() {
            return Err(AppError::CreateMessageError("files is empty".to_string()));
        }
        //verify user exists
        if self.user_id == 0 {
            return Err(AppError::CreateMessageError("user not exists".to_string()));
        }
        //verify chat exists
        if self.chat_id == 0 {
            return Err(AppError::CreateMessageError("chat not exists".to_string()));
        }

        let res = sqlx::query(
            r#"
                    INSERT INTO message (user_id,chat_id,content,files) VALUES (?,?,?,?)
                "#,
        )
        .bind(self.user_id)
        .bind(self.chat_id)
        .bind(self.content.clone())
        .bind(self.files.clone())
        .execute(pool)
        .await?;
        if res.rows_affected() == 0 {
            return Err(AppError::CreateMessageError(
                "insert message error".to_string(),
            ));
        }

        Ok(res.last_insert_id())
    }

    pub async fn count_by_chat_id(chat_id: i32, pool: &MySqlPool) -> Result<i64, AppError> {
        // 查询总数
        sqlx::query_scalar("SELECT COUNT(*) where chat_id = ?  FROM chats")
            .bind(chat_id)
            .fetch_one(pool)
            .await
            .map_err(AppError::SqlxError)
    }

    pub async fn list_by_chat_id(
        chat_id: i32,
        offset: i32,
        size: i32,
        pool: &MySqlPool,
    ) -> Result<Vec<Message>, AppError> {
        sqlx::query_as("SELECT * FROM message where chat_id=? LIMIT ?  OFFSET ? ")
            .bind(chat_id)
            .bind(size)
            .bind(offset)
            .fetch_all(pool)
            .await
            .map_err(AppError::SqlxError)
    }
}
